/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package assisisw.smartcal.entitysubsystem;

import assisisw.smartcal.entitysubsystem.exceptions.calendar.CalendarDoubleSharingNotAllowedException;
import assisisw.smartcal.entitysubsystem.exceptions.calendar.CalendarException;
import assisisw.smartcal.entitysubsystem.exceptions.calendar.CalendarSelfSharingNotAllowedException;
import assisisw.smartcal.notificationsubsystem.IEntityControllerObserver;
import assisisw.smartcal.persistencesubsystem.IDAOProvider;
import java.util.Collection;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;

/**
 *
 * @author Francesco
 */
@Stateless ()
@TransactionManagement ( value = TransactionManagementType.CONTAINER )
public class CalendarController implements ICalendarController
{
    
    // Instance Fields
    
    /***/
    @EJB ()
    private IDAOProvider daoProvider ;
    
    /***/
    @EJB ()
    private IEntityControllerObserver entityControllerObserver ;
    
    // Instance Methods
    
    /***/
    public CalendarController () {}
    
    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public void insert ( Calendar calendar , User user ) 
    {
        User owner ;
        Calendar toInsert ;
        if ( calendar != null )
        {
            //owner = daoProvider.getUserDAO().findByMail ( user.getMail () ) ;
            toInsert = new Calendar ( calendar.getName() , calendar.getColor () , user ) ;
            calendar.setOwner(user); 
            user.getOwnedCalendars().add ( calendar ) ;
            //owner.getOwnedCalendars().add ( toInsert ) ;
            daoProvider.getCalendarDAO ().insert ( toInsert ) ;
            calendar.setId ( toInsert.getId () ) ;
        }
        else
            throw new IllegalArgumentException () ;
    }
 
    /**
     * @param owner
     * @param name
     * @return
     * @throws NoSuchElementException
     */
    /*@Override
    public Calendar getOwnedByOwnerAndName ( User owner , String name ) 
    {
        Calendar res ;
        res = null ;
        for ( Calendar c : owner.getOwnedCalendars () )
            if ( c.getName().equalsIgnoreCase(name) )
            {
                res = c ;
                break ;
            }
        return res ;
    }*/
    
    /**
     * @param c
     */
    @Override
    public void update ( Calendar c )  
    {
        Calendar toUpdate ;
        if ( c != null )
        {
            toUpdate = daoProvider.getCalendarDAO().findById ( c.getId () ) ;
            Calendar.copySimpleDate ( c , toUpdate ) ;
            daoProvider.getCalendarDAO().update ( toUpdate ) ;
            for ( User u : c.getPeopleWhoCanAccess () )
                entityControllerObserver.addNotification ( Notification.NotificationType.SHARING , null , u , "Calendar " + c.getName() + " updated !") ;
        }
        else
            throw new IllegalArgumentException () ;
    }
    
    /**
     * @param c
     * @param u
     * @return
     * @throws IllegalArgumentException
     */
    public boolean canAccess ( Calendar c , User u ) 
    {
        boolean res ;
        if ( c != null && u != null )
            res = c.getOwner().equals ( u ) || c.getPeopleWhoCanAccess().contains(u);
        else
            throw new IllegalArgumentException () ;
        return res ;
    }
    
    /**
     * @param c
     * @param inviteds
     * @throws IllegalArgumentException
     * @throws CalendarSelfSharingNotAllowedException
     * @throws CalendarDoubleSharingNotAllowedException
     */
    @Override
    public void share ( Calendar c , Collection < User > inviteds ) throws CalendarException 
    {
        if ( c != null && inviteds != null )
        {
            if ( ! inviteds.contains ( c.getOwner () ) )
            {
                for ( User u : inviteds )
                    if ( canAccess ( c , u ) )
                        throw new CalendarDoubleSharingNotAllowedException ( c , u ) ;
                // effectively add the data
                for ( User u : inviteds )
                {    
                    u.getSharedCalendars ().add ( c ) ;
                    c.getPeopleWhoCanAccess().add ( u ) ;
                }                        
                daoProvider.getCalendarDAO().update ( c ) ;
                // should I update also the inviteds in the db ?
                for ( User u : c.getPeopleWhoCanAccess () )
                    entityControllerObserver.addNotification ( Notification.NotificationType.SHARING , null, u , c.getOwner().getMail() + " has shared his " + c.getName() + " calendar with you !" );
            }
            else
                throw new CalendarSelfSharingNotAllowedException ( c ) ;
        }
        else
            throw new IllegalArgumentException () ;
    }
    
    /**
     * AS THE SUPER'S ONE.
     */
    @Override
    public void delete ( Calendar c ) 
    {
        Calendar toDelete ;
        if ( c != null )
        {
            //for ( User u : c.getPeopleWhoCanAccess() )
                //u.getSharedCalendars().remove(c);
            //for ( Event e : c.getContainedEvents() )
            //{
                //daoProvider.getEventDAO().delete(e); 
                //e.getNotifications().clear(); ;
            //}
            //c.getPeopleWhoCanAccess().forEach ( ( u ) -> { u.getSharedCalendars ().remove ( c ) ; } ) ;
            //c.getContainedEvents().forEach ( ( e ) -> { daoProvider.getEventDAO ().delete(e); } ) ;
            //c.getContainedEvents().forEach ( ( e ) -> { e.getNotifications().clear () ; }) ;
            //c.getContainedEvents().clear () ;
            //c.getPeopleWhoCanAccess ().clear () ;
            toDelete = daoProvider.getCalendarDAO().findById ( c.getId () ) ;
            daoProvider.getCalendarDAO ().delete ( toDelete ) ;
            // notification to the ones this calendar is shared with
            for ( User u : c.getPeopleWhoCanAccess() )
                entityControllerObserver.addNotification ( Notification.NotificationType.SHARING , null , u , c.getName() + " has deleted his " + c.getName() + " calendar !" ) ;
        }
        else
            throw new IllegalArgumentException () ;
    }

    @Override
    public void unShare(Calendar c, User u) {
    }
    
}
